package com.bes.bessdk.service.commandset;


import static com.bes.bessdk.BesSdkConstants.BES_CONNECT_ERROR;
import static com.bes.bessdk.BesSdkConstants.BES_CONNECT_SUCCESS;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_BATTERY_BOX;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_BATTERY_LEFT;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_BUTTON_SETTINGS_CONTROL;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_BATTERY_RIGHT;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_BES_SPATIAL_SWITCH;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_BUTTON_SETTINGS_CONTROL;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_BUTTON_STATUS;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_CEVA_SWITCH;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_CURRENT_PRODUCT_MODEL;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_DATA;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_DOLBY_SWITCH;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_DOLBY_SWITCH_AND_PARAM;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_EQ_SWITCH;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_IN_EAR_DETECTION_RESULT;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_IS_FIT;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_MIMI_INTENSITY;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_MIMI_SET_PRESENT_RESULT;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_MIMI_SWITCH;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_MIMI_TECH_LEVEL;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_MULTIPOINT_STATE;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_REGULATE_ANC;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_SPP_CONNECT_STATUS;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_START_OTA;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_SWITCH_ROLE;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_TWS_AND_MASTER_STATE;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_VERSION_CRC;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_RECEIVE_WD_PROMPT_RESULT;
import static com.bes.bessdk.service.commandset.CommandSetConstants.COMMAND_SET_TYPE_MIMI_SWITCH;
import static com.bes.bessdk.service.commandset.CommandSetConstants.MSG_COMMSND_SET_ROLE_SWITCH_SCAN_TIME_OUT;
import static com.bes.bessdk.service.commandset.CommandSetConstants.SWITCH_STATUS_SET_PARAM;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import androidx.annotation.NonNull;

import com.bes.bessdk.scan.BtHeleper;
import com.bes.bessdk.service.base.BesBaseService;
import com.bes.bessdk.service.base.BesServiceConfig;
import com.bes.bessdk.service.base.BesServiceListener;
import com.bes.bessdk.utils.ArrayUtil;
import com.bes.sdk.device.HmDevice;
import com.bes.sdk.message.BaseMessage;
import com.bes.sdk.utils.DeviceProtocol;

public class CommandSetService extends BesBaseService {

    private boolean isReceiveRoleSwitch = false;
    private String roleSwitchMark = "";
    private String roleSwitchMark2 = "";

    public CommandSetService(BesServiceConfig serviceConfig, BesServiceListener listener, Context context) {
        super(serviceConfig, listener, context);
        LOG(TAG, "CommandSetService");

        startConnect(serviceConfig);
    }

    @Override
    public void onStatusChanged(HmDevice device, int status, DeviceProtocol protocol) {
        super.onStatusChanged(device, status, protocol);
        if (status == BES_CONNECT_ERROR) {
            if (isReceiveRoleSwitch) {
                scanToReConnected();
                return;
            }
            callBackStateChangedMessage(BES_CONNECT_ERROR,"error");
        } else if (status == BES_CONNECT_SUCCESS) {
            isReceiveRoleSwitch = false;
        }
    }

    @Override
    public void onDataReceived(BaseMessage deviceMessage) {
        super.onDataReceived(deviceMessage);
        Log.i(TAG, "onDataReceived: -----" + ArrayUtil.toHex((byte[]) deviceMessage.getMsgContent()));
        if (mConfig.getTotaConnect() && !totauccess) {
            return;
        }

        callBackStateChangedMessage(COMMAND_SET_RECEIVE_DATA, "after decode:" + ArrayUtil.toHex((byte[]) deviceMessage.getMsgContent()));

        LOG(TAG, "after decode:" + ArrayUtil.toHex((byte[]) deviceMessage.getMsgContent()));
        byte[] receiveData = (byte[]) deviceMessage.getMsgContent();
        if (mConfig.getTotaConnect()) {
            byte[] contentData = new byte[receiveData.length - 4];
            System.arraycopy(receiveData, 4, contentData, 0, receiveData.length - 4);
            receiveData = contentData;
        }
        int result = CommandSetCMD.receiveData(receiveData);
        if (result == COMMAND_SET_RECEIVE_BUTTON_SETTINGS_CONTROL) {
            callBackStateChangedMessage(result, ArrayUtil.toHex(CommandSetCMD.getButtonSettingResult()));
        } else if (result == COMMAND_SET_RECEIVE_BATTERY_LEFT) {
            callBackStateChangedMessage(result, CommandSetCMD.getCurBatteryPercent() + "");
        } else if (result == COMMAND_SET_RECEIVE_BATTERY_RIGHT) {
            callBackStateChangedMessage(result, CommandSetCMD.getCurBatteryPercent() + "");
        } else if (result == COMMAND_SET_RECEIVE_BATTERY_BOX) {
            callBackStateChangedMessage(result, CommandSetCMD.getCurBatteryPercent() + "");
        } else if (result == COMMAND_SET_RECEIVE_IS_FIT) {
            callBackStateChangedMessage(result, CommandSetCMD.getCurFitStatus());
        } else if (result == COMMAND_SET_RECEIVE_IN_EAR_DETECTION_RESULT) {
            callBackStateChangedMessage(result, ArrayUtil.toHex(CommandSetCMD.getCurInEarDetectionResult()));
        } else if (result == COMMAND_SET_RECEIVE_WD_PROMPT_RESULT) {
            callBackStateChangedMessage(result, ArrayUtil.toHex(CommandSetCMD.getWdPromptResult()));
        } else if (result == COMMAND_SET_RECEIVE_SPP_CONNECT_STATUS) {
            callBackStateChangedMessage(result, CommandSetCMD.getCurSppConnectStatus() + "");
        } else if (result == COMMAND_SET_RECEIVE_BUTTON_STATUS) {
            callBackStateChangedMessage(result, ArrayUtil.toHex(CommandSetCMD.getCurButtonState()));
        } else if (result == COMMAND_SET_RECEIVE_CURRENT_PRODUCT_MODEL) {
            callBackStateChangedMessage(result, CommandSetCMD.getCurrentProductModel());
        } else if (result == COMMAND_SET_RECEIVE_REGULATE_ANC) {
            callBackStateChangedMessage(result, ArrayUtil.toHex(new byte[]{CommandSetCMD.getCurANCState()}));
        } else if (result == COMMAND_SET_RECEIVE_EQ_SWITCH) {
            callBackStateChangedMessage(result, ArrayUtil.toHex(ArrayUtil.byteMerger(new byte[]{CommandSetCMD.getCurEQState(), CommandSetCMD.getCurEQStateType()}, CommandSetCMD.getCurCustomEQ())));
        } else if (result == COMMAND_SET_RECEIVE_DOLBY_SWITCH) {
            callBackStateChangedMessage(result, ArrayUtil.toHex(new byte[]{CommandSetCMD.getCurDolbyState()}));
        } else if (result == COMMAND_SET_RECEIVE_DOLBY_SWITCH_AND_PARAM) {
            callBackStateChangedMessage(COMMAND_SET_RECEIVE_DOLBY_SWITCH, ArrayUtil.toHex(new byte[]{CommandSetCMD.getCurDolbyState(), CommandSetCMD.getCurDolbyParamState()}));
        } else if (result == COMMAND_SET_RECEIVE_BES_SPATIAL_SWITCH) {
            callBackStateChangedMessage(result, ArrayUtil.toHex(new byte[]{CommandSetCMD.getCurBesSpatialState()}));
        } else if (result == COMMAND_SET_RECEIVE_MIMI_SWITCH) {
            callBackStateChangedMessage(result, ArrayUtil.toHex(new byte[]{CommandSetCMD.getCurMimiState()}));
        } else if (result == COMMAND_SET_RECEIVE_MIMI_SET_PRESENT_RESULT) {
            callBackStateChangedMessage(result, ArrayUtil.toHex(new byte[]{CommandSetCMD.getCurMimiPresetSetState()}));
        } else if (result == COMMAND_SET_RECEIVE_CEVA_SWITCH) {
            callBackStateChangedMessage(result, ArrayUtil.toHex(new byte[]{CommandSetCMD.getCurCEVAState()}));
        } else if (result == COMMAND_SET_RECEIVE_VERSION_CRC) {
            callBackStateChangedMessage(result, CommandSetCMD.getCrcAndVersionStr());
        } else if (result == COMMAND_SET_RECEIVE_START_OTA) {
            callBackStateChangedMessage(result, "");
        } else if (result == COMMAND_SET_RECEIVE_TWS_AND_MASTER_STATE) {
            callBackStateChangedMessage(result, ArrayUtil.toHex(new byte[]{CommandSetCMD.getCurTWSState(), CommandSetCMD.getCurMasterState()}));
        } else if (result == COMMAND_SET_RECEIVE_MULTIPOINT_STATE) {
            callBackStateChangedMessage(result, ArrayUtil.toHex(new byte[]{CommandSetCMD.getCurMultiPiontState()}));
        } else if (result == COMMAND_SET_RECEIVE_MIMI_TECH_LEVEL) {
            callBackStateChangedMessage(result, CommandSetCMD.getCurMimiTechLevel() + "");
        } else if (result == COMMAND_SET_RECEIVE_MIMI_INTENSITY) {
            callBackStateChangedMessage(result, CommandSetCMD.getCurMimiIntensity() + "");
        } else if (result == COMMAND_SET_RECEIVE_SWITCH_ROLE) {
            if (mConfig.getDeviceProtocol() == DeviceProtocol.PROTOCOL_BLE) {
                isReceiveRoleSwitch = true;
                roleSwitchMark = ArrayUtil.toHex(CommandSetCMD.getCurRoleSwitchMarkData()).replace(",", "");
                roleSwitchMark2 = ArrayUtil.toHex(CommandSetCMD.getCurRoleSwitchMarkData2()).replace(",", "");
                LOG(TAG, "COMMAND_SET_RECEIVE_SWITCH_ROLE:" + roleSwitchMark);
                LOG(TAG, "COMMAND_SET_RECEIVE_SWITCH_ROLE2:" + roleSwitchMark2);
                callBackStateChangedMessage(result, "");
            }
        }
    }

    public void sendTestData(Byte cmdType, boolean hasType, Byte...type) {
        Log.i(TAG, "sendTestData: ------" + ArrayUtil.toHex(CommandSetCMD.getCurCommand(cmdType, hasType, type)));
        byte[] data = CommandSetCMD.getCurCommand(cmdType, hasType, type);
        LOG(TAG, "send data:" + ArrayUtil.toHex(data));
        sendData(data);
        callBackStateChangedMessage(COMMAND_SET_RECEIVE_DATA, "send data:" + ArrayUtil.toHex(data));
    }

    public void sendMimiSetPresentData(byte[] param) {
        byte[] presentID = new byte[32];
        Log.i(TAG, "sendMimiSetPresentData: -----------");
        byte[] lastData = ArrayUtil.bytesSplic(new byte[]{COMMAND_SET_TYPE_MIMI_SWITCH, SWITCH_STATUS_SET_PARAM}, param, ArrayUtil.dataToMD5(param), presentID);
        LOG(TAG, "sendMimiSetPresentData: ------" + ArrayUtil.toHex(lastData));
        byte[] curData = CommandSetCMD.getCurMimiSetPresent(lastData);
        LOG(TAG, "sendMimiSetPresentData data:" + ArrayUtil.toHex(curData));
        sendData(curData);
        callBackStateChangedMessage(COMMAND_SET_RECEIVE_DATA, "sendMimiSetPresentData data:" + ArrayUtil.toHex(curData));
    }

    public void sendGetVersionCrcData() {
        sendData(CommandSetCMD.getCrcCMD());
        callBackStateChangedMessage(COMMAND_SET_RECEIVE_DATA, "sendGetVersionCrcData data:" + ArrayUtil.toHex(CommandSetCMD.getCrcCMD()));
    }

    private BluetoothLeScanner mLeScanner;
    @SuppressLint("MissingPermission")
    private void scanToReConnected() {
        if (mLeScanner != null) {
            mLeScanner.stopScan(mCallback);
            mLeScanner = null;
        }
        BluetoothAdapter mBluetoothAdapter = BtHeleper.getBluetoothAdapter(mContext);
        mLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
        mLeScanner.startScan(null, new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(), mCallback);
        addTimeOutMsg(besCommandSetMsgHandler, 5000, MSG_COMMSND_SET_ROLE_SWITCH_SCAN_TIME_OUT);
    }

    private android.bluetooth.le.ScanCallback mCallback = new android.bluetooth.le.ScanCallback() {
        @Override
        public void onScanFailed(int errorCode) {
            super.onScanFailed(errorCode);
            LOG(TAG, "onScanFailed: ---------fail");
            callBackStateChangedMessage(COMMAND_SET_RECEIVE_DATA, "onScanFailed: ---------fail");
            scanToReConnected();
        }
        @SuppressLint("MissingPermission")
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            String resultStr = ArrayUtil.bytesToHexString(result.getScanRecord().getBytes());
//            callBackStateChangedMessage(COMMAND_SET_RECEIVE_DATA, "onScanSuccess: ---------" + resultStr);
            LOG(TAG, "onScanSuccess: ---------" + resultStr);

            if (roleSwitchMark.length() > 0 && (resultStr.contains(roleSwitchMark) || resultStr.contains(roleSwitchMark2))) {
                LOG(TAG, "match Success: ---------" + resultStr);
                removeTimeoutMsg(besCommandSetMsgHandler, MSG_COMMSND_SET_ROLE_SWITCH_SCAN_TIME_OUT);
                if (mLeScanner != null) {
                    mLeScanner.stopScan(mCallback);
                    mLeScanner = null;
                }
                HmDevice hmDevice = mConfig.getDevice();
                hmDevice.setBleAddress(result.getDevice().getAddress());
                mConfig.setDevice(hmDevice);
                LOG(TAG, "connect: ---------" + mConfig.getDevice().getBleAddress());
                startConnect(mConfig);
            }
        }
    };

    private Handler besCommandSetMsgHandler = new Handler(mHandlerThread.getLooper()) {
        @SuppressLint("MissingPermission")
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            LOG(TAG, "besCommandSetMsgHandler-----");
            switch (msg.what) {
                case MSG_COMMSND_SET_ROLE_SWITCH_SCAN_TIME_OUT:
                    if (mLeScanner != null) {
                        mLeScanner.stopScan(mCallback);
                        mLeScanner = null;
                    }
                    isReceiveRoleSwitch = false;

                    callBackStateChangedMessage(BES_CONNECT_ERROR, "DISCONNECT");
                    break;
                default:
                    break;
            }
        }
    };
}
